#pragma once

#include <iostream>
#include <sstream>
#include <cassert>
#include <iterator>
#include <algorithm>

#define STATIC_ASSERT(x) {typedef char T[(x) ? 1 : -1];}
//#define STATIC_ASSERT(x) {struct sa_struct{ unsigned int val : (x) ? 1 : -1; };}
//#define STATIC_ASSERT(x) {enum {sa_enum = 1/(x)};}
//#define STATIC_ASSERT(x) {sizeof(char[1 - 2*!(x)]);}

namespace Utilities
{

template<typename T>
inline T& Max2(T& a, T& b)
{
	return a < b ? b : a;
}

template<typename T>
inline T& Max3(T& a, T& b, T& c)
{
	return Max2(Max2(a,b),c);
}

template<typename T>
inline T& Max4(T& a, T& b, T& c, T& d)
{
	return Max2(Max2(a,b), Max2(c,d));
}

inline int StringToInt(std::string i_string)
{
	int number = 0;
	int exp = 1;
	for (int i = i_string.length() - 1 ; i >= 0 ; --i)
	{

		if (i_string[i] < '0' || i_string[i] > '9')
			return -1;
		number += (i_string[i] - '0') * exp;
		exp *= 10;
	}
	return number;
}

inline std::string IntToString(const int i)
{
	std::stringstream ss;
	ss << i;
	return ss.str();
}

inline size_t GetMCD(const size_t i_first, const size_t i_second)
{
	size_t num1(i_first);
	size_t num2(i_second);

	if (num1 < num2)
			std::swap(num1,num2);

	while (num2)
	{
			num1 = num1 % num2;
			std::swap(num1,num2);
	}
	return num1;
}

inline size_t GetMCM(const size_t i_first, const size_t i_second)
{
	//don't know if it's better to evaulate MCM with respect MCD
	//or to write in place a solution
	const size_t ret = (i_first/GetMCD(i_first, i_second))*i_second;
	return ret;
}

template<typename Container>
inline void RemoveAll(Container& o_container, const typename Container::value_type& i_value)
{
	o_container.erase(std::remove(o_container.begin(), o_container.end(), i_value), o_container.end());
}


template<typename Container>
inline void DeepClear(Container& o_container)
{
	typedef typename Container::iterator Iter;
	for(Iter i = o_container.begin(); i != o_container.end(); ++i)
		delete *i;
	o_container.clear();
}

template<typename Container>
inline void Append(Container& o_dest, const Container& i_src)
{
	o_dest.reserve(o_dest.size() + i_src.size());
	std::copy(i_src.begin(), i_src.end(), std::back_inserter(o_dest));
}

}

class ZVariant
{
public:

	enum ValueType
	{
		INT		= 0,
		FLOAT,
		BOOL,
		CHAR
	};

	template<typename T>
	T Get()
	{
		return *reinterpret_cast<T*>(&Float);
	}

	template<typename T>
	void Set(const T& i_value)
	{
		assert(0 && "No value type!");
	}

	void Set(const char& i_value)
	{
		Char = i_value;
		m_type = CHAR;
	}

	void Set(const int& i_value)
	{
		Int = i_value;
		m_type = INT;
	}

	void Set(const float& i_value)
	{
		Float = i_value;
		m_type = FLOAT;
	}

	void Set(const bool& i_value)
	{
		Bool = i_value;
		m_type = BOOL;
	}

	bool IsInt() const
	{
		return m_type == INT;
	}

	bool IsFloat() const
	{
		return m_type == FLOAT;
	}

	bool IsBool() const
	{
		return m_type == BOOL;
	}

	bool IsChar() const
	{
		return m_type == CHAR;
	}

	operator char() const
	{
		assert(IsChar() && "Not a char!");
		return Char;
	}

	operator int() const
	{
		assert(IsInt() && "Not a int!");
		return Int;
	}

	operator bool() const
	{
		assert(IsBool() && "Not a bool!");
		return Bool;
	}

	operator float() const
	{
		assert(IsFloat() && "Not a float!");
		return Float;
	}

private:

	union
	{
		char	Char;
		int		Int;
		float	Float;
		bool	Bool;
	};

	ValueType	m_type;
};